<script lang="ts" setup>
import { i18n } from "@/locales";
import type { NodeViewProps } from "@/tiptap/vue-3";
import { NodeViewWrapper } from "@/tiptap/vue-3";
import { computed, onMounted, ref } from "vue";
import Image from "./index";
import ImagePreview from "./ImagePreview.vue";

const props = defineProps<NodeViewProps>();

const src = computed({
  get: () => {
    return props.node?.attrs.src;
  },
  set: (src: string) => {
    props.updateAttributes({
      src: src,
    });
  },
});

const alt = computed({
  get: () => {
    return props.node?.attrs.alt;
  },
  set: (alt: string) => {
    props.updateAttributes({ alt: alt });
  },
});

const href = computed({
  get: () => {
    return props.node?.attrs.href;
  },
  set: (href: string) => {
    props.updateAttributes({ href: href });
  },
});

function handleSetFocus() {
  props.editor.commands.setNodeSelection(props.getPos() || 0);
}

const aspectRatio = ref<number>(0);
const inputRef = ref();
const resizeRef = ref<HTMLDivElement>();

// 图片预览相关
const previewVisible = ref(false);
const previewImages = ref<Array<{ src: string; alt?: string }>>([]);
const previewCurrent = ref(0);

// 判断是否为只读模式
const isReadOnly = computed(() => !props.editor.isEditable);

function onImageLoaded() {
  if (!resizeRef.value) return;

  aspectRatio.value =
    resizeRef.value.clientWidth / resizeRef.value.clientHeight;
}

// 处理图片点击预览
function handleImageClick(event: MouseEvent) {
  // 只在只读模式下启用预览
  if (!isReadOnly.value) return;
  
  event.preventDefault();
  event.stopPropagation();
  
  // 收集编辑器中所有图片
  const allImages: Array<{ src: string; alt?: string }> = [];
  let clickedIndex = 0;
  
  props.editor.state.doc.descendants((node, pos) => {
    if (node.type.name === 'image' && node.attrs.src) {
      if (pos === props.getPos()) {
        clickedIndex = allImages.length;
      }
      allImages.push({
        src: node.attrs.src,
        alt: node.attrs.alt
      });
    }
  });
  
  previewImages.value = allImages;
  previewCurrent.value = clickedIndex;
  previewVisible.value = true;
}

onMounted(() => {
  if (!src.value) {
    inputRef.value.focus();
    return;
  }

  if (!resizeRef.value) return;

  let startX: number, startWidth: number;

  resizeRef.value.addEventListener("mousedown", function (e) {
    startX = e.clientX;
    startWidth = resizeRef.value?.clientWidth || 1;
    document.documentElement.addEventListener("mousemove", doDrag, false);
    document.documentElement.addEventListener("mouseup", stopDrag, false);
  });

  function doDrag(e: MouseEvent) {
    if (!resizeRef.value) return;

    const newWidth = Math.min(
      startWidth + e.clientX - startX,
      resizeRef.value.parentElement?.clientWidth || 0
    );

    const width = newWidth.toFixed(0) + "px";
    const height = (newWidth / aspectRatio.value).toFixed(0) + "px";
    props.editor
      .chain()
      .updateAttributes(Image.name, { width, height })
      .setNodeSelection(props.getPos() || 0)
      .focus()
      .run();
  }

  function stopDrag() {
    document.documentElement.removeEventListener("mousemove", doDrag, false);
    document.documentElement.removeEventListener("mouseup", stopDrag, false);
  }
});
</script>

<template>
  <node-view-wrapper as="div" class="image-wrapper">
    <div v-if="!src" class="image-input-wrapper">
      <input
        ref="inputRef"
        v-model.lazy="src"
        class="image-input"
        :placeholder="i18n.global.t('editor.common.placeholder.link_input')"
        tabindex="-1"
        @focus="handleSetFocus"
      />
    </div>
    <div
      v-else
      ref="resizeRef"
      class="image-container"
      :class="{
        'is-selected': selected,
        'is-readonly': isReadOnly,
      }"
      :style="{
        width: node.attrs.width,
        height: node.attrs.height,
      }"
    >
      <img
        :src="src"
        :title="node.attrs.title"
        :alt="alt"
        :href="href"
        class="image-element"
        @load="onImageLoaded"
        @click="handleImageClick"
      />
    </div>
    
    <!-- 图片预览组件 -->
    <ImagePreview
      v-model:visible="previewVisible"
      v-model:current="previewCurrent"
      :images="previewImages"
    />
  </node-view-wrapper>
</template>

<style lang="scss" scoped>
.image-wrapper {
  display: inline-block;
  width: 100%;
}

.image-input-wrapper {
  width: 100%;
  padding: 0.375rem; // p-1.5
}

.image-input {
  display: block;
  width: 100%;
  border-radius: 0.375rem; // rounded-md
  border: 1px solid var(--editor-input-border);
  background-color: var(--editor-input-bg);
  padding: 0.375rem 0.5rem; // px-2 py-1.5
  font-size: 0.875rem; // text-sm
  color: var(--editor-input-text);

  &:focus {
    border-color: var(--editor-input-focus-border);
    outline: none;
    box-shadow: 0 0 0 1px var(--editor-input-focus-border);
  }
}

.image-container {
  position: relative;
  display: inline-block;
  max-width: 100%;
  resize: horizontal;
  overflow: hidden;
  border-radius: 0.375rem; // rounded-md
  text-align: center;

  &.is-selected {
    border-radius: 0.25rem; // rounded
    box-shadow: 0 0 0 2px var(--editor-primary-color); // ring-2
  }
  
  &.is-readonly {
    resize: none;
    
    .image-element {
      cursor: pointer;
      transition: opacity 0.2s ease;
      
      &:hover {
        opacity: 0.85;
      }
    }
  }
}

.image-element {
  height: 100%;
  width: 100%;
}
</style>
